/*
 * cm_storage.h
 *
 *  Created on: 2014年7月21日
 *      Author: chens
 */

#ifndef CM_STORAGE_H_
#define CM_STORAGE_H_

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <cm/cm_constant.h>

#ifdef __cplusplus
extern "C" {
#endif

/* Readme:
 * 	仓库用来存放各种类型的数据，仓库的类型主要根据存储介质不同来划分
 * 	在构造一个仓库的时候，需要提供所存放数据的序列化函数和反序列化函数
 * 	每个仓库只用于存放一种数据（使用相同的序列化方法），每个数据在仓库中处于不同的状态
 * 	仓库为每个数据保存一份额外的信息，记录入库时间、状态改变时间等(struct cm_storage_head)
 */

/* @brief	内部实现的仓库类型的申明 */
typedef struct cm_storage cm_storage;

/* 仓库的类型 */
enum CM_STORAGE_TYPE {
	CM_STORAGE_DB, /* 以数据库的方式存储 */
	CM_STORAGE_FILE, /* 以文件的方式存储 */
	CM_STORAGE_MEM /* 存储在内存中 */
};

/*
 * @brief	创建一个仓库
 * @param	type：仓库类型，用文件或数据库
 * 		objsize：仓库中每个元素的大小(序列化后最大大小)
 * 		url：数据库文件路径 或 数据文件路径
 * 		serialize：仓库中所存数据使用的序列化方法
 * 		unserialize：仓库中所存数据所使用的反序列化方法
 * 		serialize和unserialize如果为NULL的话表示数据可以不做转换直接进行存储
 * @return	成功返回0 失败返回非0
 *
 */
cm_storage* cmstorage_create(enum CM_STORAGE_TYPE type, int objsize,
		const char *url, cm_serialize serialize,
		cm_unserialize unserialize);

/*
 * @brief	关闭一个仓库
 * @param	指向仓库对象指针的指针
 * @return	*t所指向的仓库被关闭且 *t的值置为NULL
 */
void cmstorage_close(cm_storage **t);

/* 存储状态 */
enum CM_STORAGE_STATE {
	CM_STORAGE_NOMAL, CM_STORAGE_EXPIRE
};

/*
 * @brief	仓库中数据的额外信息，存储在每一条数据的前面
 */
struct cmstorage_head {

	/* 指示该条数据是否有效 */
	int valid;

	/* 该条数据的创建时间 */
	struct timeval create_time;

	/* 上一次状态改变的时间 */
	struct timeval state_change;

	/* 数据的当前状态 */
	enum CM_STORAGE_STATE state;
};

#define LEN_CM_STORAGE_HEAD (sizeof(struct cmstorage_head))

/*
 * @brief	将数据放入仓库
 * @param	t: 是一个指向仓库对象的指针
 * 		data: 指向要放入仓库的数据
 * 		state: 放入对象的状态
 * @return	0表示成功，非0表示失败
 */
int cmstorage_put(const cm_storage *t, void *data, enum CM_STORAGE_STATE state);

/* 取数据时排序的方式 */
enum CM_STORAGE_SORT {
	/* 默认排序方式 */
	CM_STORAGE_SORT_DEFAULT,

	/* 按入库时间降序，晚入库的优先 */
	CM_STORAGE_SORT_CREATETIME_DESC,

	/* 按入库时间升序，早入库的优先 */
	CM_STORAGE_SORT_CREATETIME_ASC
};

/*
 * @brief	将一条数据从仓库中取出，数据格式使用仓库的unserialize函数解析
 * @param	t: 仓库对象
 * 		sort：取数据时采用的排序方式
 * 		cond：用来比较是否满足条件
 * 		data与size指定用来存放数据的空间及空间大小
 * 		head：用来存放数据的额外信息，可以传递NULL
 * @return	成功则返回一个非负（可为0）的数据ID，失败返回-1
 */
int cmstorage_get(const cm_storage *t, enum CM_STORAGE_SORT sort,
		cm_satisfy cond, char *data, size_t size,
		struct cmstorage_head* head);

#ifdef __cplusplus
}
#endif

#endif /* CM_STORAGE_H_ */
